package com.retry.task.admin.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

/**
 * @author gao.gwq
 * @version 1.0
 * @date 2021/9/4  2:22 下午
 * @Description TODO
 */
public class DateUtils {
    public final static String TIME_YYYMMDD = "yyyyMMdd";

    public final static String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public final static String DATE_FORMAT = "yyyy-MM-dd";

    public final static String DATE_FORMAT_NUMBER = "yyyyMMdd";

    public final static String TIME_FORMAT = "HH:mm:ss";

    public final static String DIFF_DAY = "dd";

    public final static String DIFF_HOUR = "hh";

    public final static String DIFF_MINUTE = "mi";

    public final static String DIFF_SECOND = "ss";

    public final static String DIFF_MILLISECOND = "ms";

    public static final int INDEX_YEAR = 0;
    public static final int INDEX_MONTH = 1;
    public static final int INDEX_DAY = 2;
    public static final int INDEX_HOUR = 3;
    public static final int INDEX_MINUTE = 4;
    public static final int INDEX_SECOND = 5;
    public static final int INDEX_MILLISECOND = 6;

    /**
     * 获取当前系统时间
     *
     * @return Date
     */
    public static Date getCurrDate() {
        return new Date();
    }

    /**
     * 获取当前日期，精确到天
     *
     * @return
     */
    public static Date getCurrDay() {
        Date now = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(now);
        // 将时分秒,毫秒域清零
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取当前年
     *
     * @return [2018]
     */
    public static int getCurrentYear() {
        Calendar cal = Calendar.getInstance();
        return cal.get(Calendar.YEAR);
    }

    /**
     * 获取当前月份
     *
     * @return mm [1-12]
     */
    public static int getCurrentMonth() {
        Calendar cal = Calendar.getInstance();
        return cal.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取当前天数
     *
     * @return DD[1-31]
     */
    public static int getCurrentDay() {
        Calendar cal = Calendar.getInstance();
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取指定时间格式的年月日
     *
     * @param dateStr
     * @param dateFormat
     * @return <li>
     * <ul>day 整数数组</ul>
     * <ul>day[0]   年</ul>
     * <ul>day[1]   月</ul>
     * <ul>day[2]   日</ul>
     * <ul>day[3]   时</ul>
     * <ul>day[4]   分</ul>
     * <ul>day[5]   秒</ul>
     * <ul>day[6]   毫秒</ul>
     * </li>
     * @throws ParseException
     */
    public static int[] getDateMeta(String dateStr, String dateFormat) throws ParseException {
        int[] day = new int[6];
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);

        Date date = sdf.parse(dateStr);
        return getDateMeta(date);
    }

    /**
     * 获取指定时间格式的年，月，日，时，分，秒，毫秒
     *
     * @param date
     * @return <li>
     * <ul>day 整数数组</ul>
     * <ul>day[0]   年</ul>
     * <ul>day[1]   月</ul>
     * <ul>day[2]   日</ul>
     * <ul>day[3]   时</ul>
     * <ul>day[4]   分</ul>
     * <ul>day[5]   秒</ul>
     * <ul>day[6]   毫秒</ul>
     * </li>
     * @throws ParseException
     */
    public static int[] getDateMeta(Date date) {
        int[] day = new int[7];

        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        day[INDEX_YEAR] = cal.get(Calendar.YEAR);
        day[INDEX_MONTH] = cal.get(Calendar.MONTH) + 1;
        day[INDEX_DAY] = cal.get(Calendar.DAY_OF_MONTH);
        day[INDEX_HOUR] = cal.get(Calendar.HOUR_OF_DAY);
        day[INDEX_MINUTE] = cal.get(Calendar.MINUTE);
        day[INDEX_SECOND] = cal.get(Calendar.SECOND);
        day[INDEX_MILLISECOND] = cal.get(Calendar.MILLISECOND);
        return day;
    }

    /**
     * 获取当前天数
     *
     * @return DD[1-31]
     */
    public static int getWeekOfCurrentDay() {
        Calendar cal = Calendar.getInstance();
        return cal.get(Calendar.DAY_OF_WEEK) - 1;
    }

    /**
     * 时间格式化
     *
     * @param date
     * @param formatPattern
     * @return java.lang.String
     */
    public static String format(Date date, String formatPattern) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat f = new SimpleDateFormat(formatPattern);
        return f.format(date);
    }

    /**
     * 文本转换成时间
     *
     * @param text
     * @param formatPattern
     * @return java.util.Date
     */
    public static Date parse(String text, String formatPattern) throws ParseException {
        if (StringUtils.isBlank(text)) {
            return null;
        }
        SimpleDateFormat f = new SimpleDateFormat(formatPattern);
        return f.parse(text);
    }

    /**
     * 得到monthAfter月后的最后一天，最后一秒 例如：当前时间2015-08-18 10:30:00,monthMonth=1, 返回结果：2015-09-30 23:59:59
     *
     * @param monthAfter
     * @return
     */
    public static Date getShowEndDate(Integer monthAfter) {
        // 读取配置表中配置
        Calendar nowDate = Calendar.getInstance();
        nowDate.add(Calendar.MONTH, monthAfter);
        nowDate.set(Calendar.DATE, 1);
        nowDate.roll(Calendar.DATE, -1);
        nowDate.set(Calendar.HOUR_OF_DAY, 23);
        nowDate.set(Calendar.MINUTE, 59);
        nowDate.set(Calendar.SECOND, 59);
        nowDate.set(Calendar.MILLISECOND, 999);
        return nowDate.getTime();
    }

    /**
     * 得到某月的第一秒， 例如：当前时间year=2015,month=1, 返回结果：2015-01-01 00:00:00
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getFirstSecOfMonth(Integer year, Integer month) {
        // 读取配置表中配置
        Calendar nowDate = Calendar.getInstance();
        nowDate.set(Calendar.YEAR, year);
        nowDate.set(Calendar.MONTH, month - 1);
        nowDate.set(Calendar.DATE, 1);
        nowDate.set(Calendar.HOUR_OF_DAY, 0);
        nowDate.set(Calendar.MINUTE, 0);
        nowDate.set(Calendar.SECOND, 0);
        nowDate.set(Calendar.MILLISECOND, 0);
        return nowDate.getTime();
    }

    /**
     * 得到某月的最后一秒， 例如：当前时间year=2015,month=1, 返回结果：2015-01-31 23:59:59
     *
     * @param year
     * @param month
     * @return
     */
    public static Date getLastSecOfMonth(Integer year, Integer month) {
        // 读取配置表中配置
        Calendar nowDate = Calendar.getInstance();
        nowDate.set(Calendar.YEAR, year);
        nowDate.set(Calendar.MONTH, month - 1);
        nowDate.set(Calendar.DATE, 1);
        nowDate.roll(Calendar.DATE, -1);
        nowDate.set(Calendar.HOUR_OF_DAY, 23);
        nowDate.set(Calendar.MINUTE, 59);
        nowDate.set(Calendar.SECOND, 59);
        nowDate.set(Calendar.MILLISECOND, 999);
        return nowDate.getTime();
    }

    /**
     * 得到monthAfter月后的第一天的第一秒时间 例如：当前时间2015-08-18 10:30:00,monthMonth=1, 返回结果：2015-09-01 00:00:00
     *
     * @param monthAfter
     * @return
     */
    public static Date getShowStartDate(Integer monthAfter) {
        Calendar nowDate = Calendar.getInstance();
        nowDate.add(Calendar.MONTH, monthAfter);
        nowDate.set(Calendar.DATE, 1);
        nowDate.set(Calendar.HOUR_OF_DAY, 0);
        nowDate.set(Calendar.MINUTE, 0);
        nowDate.set(Calendar.SECOND, 0);
        nowDate.set(Calendar.MILLISECOND, 0);
        return nowDate.getTime();
    }

    /**
     * 获取上月时间的年月字符串格式，如2011-03 查询历史标王信息时使用
     *
     * @return
     */
    public static String getLastYearMonth() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Calendar nowDate = Calendar.getInstance();
        nowDate.add(Calendar.MONTH, -1);
        return sdf.format(nowDate.getTime());
    }

    /**
     * 获取上月时间的年字符串格式，如2015 查询历史标王信息时使用
     *
     * @return
     */
    public static int getLastMonthOfYear() {
        Calendar nowDate = Calendar.getInstance();
        nowDate.add(Calendar.MONTH, -1);
        return nowDate.get(Calendar.YEAR);
    }

    /**
     * 获取上月时间的月字符串格式，如03 查询历史标王信息时使用
     *
     * @return
     */
    public static int getLastMonth() {
        Calendar nowDate = Calendar.getInstance();
        nowDate.add(Calendar.MONTH, -1);
        return nowDate.get(Calendar.MONTH) + 1;
    }

    /**
     * 判断这个时间是否是这个月1号之前
     *
     * @param yearMonth 时间年月的格式如2011-03
     * @return
     * @throws ParseException
     */
    public static boolean isBeforeThisMonth(String yearMonth) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Date date = sdf.parse(yearMonth);
        Calendar nowDate = Calendar.getInstance();
        nowDate.set(Calendar.DATE, 1);
        nowDate.add(Calendar.DATE, -1);
        nowDate.set(Calendar.HOUR_OF_DAY, 23);
        nowDate.set(Calendar.MINUTE, 59);
        nowDate.set(Calendar.SECOND, 59);
        return date.before(nowDate.getTime());
    }

    /**
     * 计算2个日期(取整)相差的天数(返回值非负)
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static int getDateDistance(Date startDate, Date endDate) {
        Date[] dates = {startDate, endDate};
        Calendar[] calendars = new Calendar[2];
        for (int i = 0; i < 2; i++) {
            calendars[i] = Calendar.getInstance();
            calendars[i].setTime(dates[i]);
            // 小时取0
            calendars[i].set(Calendar.HOUR_OF_DAY, 0);
            // 分取0
            calendars[i].set(Calendar.MINUTE, 0);
            // 秒取0
            calendars[i].set(Calendar.SECOND, 0);
            // 毫秒取0
            calendars[i].set(Calendar.MILLISECOND, 0);
        }
        return Math.abs(
            (int)((calendars[0].getTime().getTime() - calendars[1].getTime().getTime()) / 1000 / 60 / 60 / 24));
    }

    /**
     * 返回指定间隔时间的日期
     *
     * @param date  指定时间
     * @param year  间隔的年数， 负数时往前推
     * @param month 间隔月数，负数往前推
     * @param day   间隔天数，负数往前推
     * @return
     */
    public static Date getAfterDate(Date date, int year, int month, int day) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.YEAR, year);
        cal.add(Calendar.MONTH, month);
        cal.add(Calendar.DAY_OF_YEAR, day);
        return cal.getTime();
    }

    /**
     * 判断两个日期是否在同一天
     *
     * @param day1 不为空
     * @param day2 不为空
     * @return
     */
    public static boolean isSameDay(Date day1, Date day2) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String day1Str = sdf.format(day1);
        String day2Str = sdf.format(day2);
        return day1Str.equals(day2Str);

    }

    /**
     * 计算2个日期(取整)相差的天数、小时数、分钟数、秒数(返回值非负)
     *
     * @param startTime
     * @param endTime
     * @param format
     * @param diffKey
     * @return
     */
    public static long dateDiff(String startTime, String endTime, String format, String diffKey) {
        //按照传入的格式生成一个simpledateformate对象
        SimpleDateFormat sd = new SimpleDateFormat(format);
        long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
        long nh = 1000 * 60 * 60;// 一小时的毫秒数
        long nm = 1000 * 60;// 一分钟的毫秒数
        long ns = 1000;// 一秒钟的毫秒数
        long diff = 0;
        long day = 0;
        long hour = 0;
        long min = 0;
        long sec = 0;
        try {
            //获得两个时间的毫秒时间差异
            diff = Math.abs(sd.parse(endTime).getTime() - sd.parse(startTime).getTime());
            day = diff / nd;// 计算差多少天
            hour = diff % nd / nh + day * 24;// 计算差多少小时
            min = diff % nd % nh / nm + hour * 60;// 计算差多少分钟
            sec = diff % nd % nh % nm / ns + min * 60;// 计算差多少秒

            if (diffKey.equalsIgnoreCase("dd")) {
                return day;
            } else if (diffKey.equalsIgnoreCase("hh")) {
                return hour;
            } else if (diffKey.equalsIgnoreCase("mi")) {
                return min;
            } else if (diffKey.equalsIgnoreCase("ss")) {
                return sec;
            } else if (diffKey.equalsIgnoreCase("ms")) {
                return diff;
            }

        } catch (ParseException e) {

        }
        return diff;
    }

    /**
     * 获取月份起始日期
     *
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date getMinMonthDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }

    /**
     * 获取月份最后日期
     *
     * @param date
     * @return
     * @throws ParseException
     */
    public static Date getMaxMonthDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }

    public static Date addMinute(Date date, int minute) {

        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        // 把当前时间往前或往后挪到指定分钟数
        calendar.add(Calendar.MINUTE, minute);
        return date = calendar.getTime();
    }

    public static Date addSecond(Date date, int seconds) {

        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        // 把当前时间往前或往后挪到指定分钟数
        calendar.add(Calendar.SECOND, seconds);
        return date = calendar.getTime();
    }

    public static Date addDay(Date date, int iday) {

        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        // 把日期往后增加一天.整数往后推,负数往前移动
        calendar.add(Calendar.DATE, iday);
        return date = calendar.getTime();
    }

    public static Date getDateMax(Date date) {

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MILLISECOND, 0);

        return c.getTime();
    }

    public static Date getDateMin(Date date) {

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);

        return c.getTime();
    }

    public static Date addMonth(Date day, int month) {

        Calendar calendar = new GregorianCalendar();
        calendar.setTime(day);
        calendar.add(Calendar.MONTH, month);
        day = calendar.getTime();
        return day;

    }

    /**
     * 返回当天的前一天的最后一秒。 当天为：2018-10-30 15:12:13 则返回：2018-10-29 23:59:59
     *
     * @return
     */
    public static Date getLastDay() {
        Calendar nowDate = Calendar.getInstance();

        nowDate.add(Calendar.DAY_OF_MONTH, -1);
        nowDate.set(Calendar.HOUR_OF_DAY, 23);
        nowDate.set(Calendar.MINUTE, 59);
        nowDate.set(Calendar.SECOND, 59);
        nowDate.set(Calendar.MILLISECOND, 0);
        return nowDate.getTime();
    }

    /**
     * 按照指定的格式，放回指定月份的所有天字符串数组 2018-10-29 2018-10-01 .... 2018-10-31
     *
     * @param month
     * @param formatPattern
     * @return
     */
    public static List<String> getDatesOfMonth(Date month, String formatPattern) {
        Date lastDayOfMonth = getMaxMonthDate(month);
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(lastDayOfMonth);
        int endDay = calendar.get(Calendar.DAY_OF_MONTH);
        SimpleDateFormat formate = new SimpleDateFormat(formatPattern);
        List<String> result = new ArrayList<>();
        for (int i = 0; i < endDay; i++) {
            result.add(formate.format(addDay(lastDayOfMonth, i - endDay + 1)));
        }
        return result;
    }

    /**
     * 按照指定的格式，放回指定月份的所有天字符串数组 2018-10-29 2018-10-01 .... 2018-10-31
     *
     * @param begin
     * @param end
     * @param formatPattern
     * @return
     */
    public static ArrayList<String> getDatesOfMonth(Date begin, Date end, String formatPattern) {

        ArrayList<String> result = new ArrayList<>();
        Date tmp = begin;
        SimpleDateFormat formate = new SimpleDateFormat(formatPattern);
        for (int i = 0; tmp.before(end); i++) {
            tmp = addDay(begin, i);
            result.add(formate.format(tmp));

        }
        return result;

    }

    /**
     * 返回多少前后多少天的date,用正负表示前后
     *
     * @param day
     * @param i
     */
    public static Date beforeOrAfterDay(Date day, int i) {
        Calendar c = Calendar.getInstance();
        c.setTime(day);
        c.add(Calendar.DAY_OF_MONTH, i);
        return c.getTime();
    }

    public static Date asDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date asDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static LocalDate asLocalDate(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static LocalDateTime asLocalDateTime(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }
}
